﻿using CS795.TravelAgency.Domain;
using CS795.TravelAgency.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.Mvc;

namespace CS795.TravelAgency.Controllers
{
    public class TripController : Controller
    {
        private TravelAgencyContext context = new TravelAgencyContext();

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents")]
        public ActionResult Customers()
        {
            IEnumerable<CustomerViewModel> model = context.Users.Include("Roles").Where(u => u.Roles.Select(r => r.Name).Contains("Customers")).Select(c => new CustomerViewModel { Id = c.Id, Name = c.Name, Email = c.Email }).AsEnumerable();
            return View(model);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult Trips(int? customerId)
        {
            IEnumerable<TripSummaryViewModel> model = null;
            if (User.IsInRole("Customers"))
            {
                Domain.Entities.User user = context.Users.Where(u => u.Name == User.Identity.Name).Single();
                ViewBag.CustomerId = user.Id;
                model = context.Trips.Where(t => t.UserId == user.Id).Select(c => new TripSummaryViewModel { Id = c.Id, Name = c.Name }).AsEnumerable();
            }
            else
            {
                if (customerId.HasValue)
                {
                    ViewBag.CustomerId = customerId.Value;
                    model = context.Trips.Where(t => t.UserId == customerId.Value).Select(c => new TripSummaryViewModel { Id = c.Id, Name = c.Name }).AsEnumerable();
                }
                else
                {
                    return RedirectToAction("Customers");
                }
            }
            return View(model);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult Create(int customerId)
        {
            ViewBag.CustomerId = customerId;
            return View();
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public ActionResult Create(TripSummaryViewModel model, int customerId)
        {
            if (ModelState.IsValid)
            {
                Domain.Entities.User user = context.Users.Where(u => u.Id == customerId).Single();
                Domain.Entities.Trip trip = new Domain.Entities.Trip
                {
                    User = user,
                    Name = model.Name
                };
                context.Trips.Add(trip);
                context.SaveChanges();
                return RedirectToAction("Trips", "Trip", routeValues: new { customerId = customerId });
            }

            ViewBag.CustomerId = customerId;
            return View(model);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult Edit(int? tripId)
        {
            Domain.Entities.Trip trip = null;
            if (User.IsInRole("Customers"))
            {
                Domain.Entities.User user = context.Users.Where(u => u.Name == User.Identity.Name).Single();
                if (!tripId.HasValue)
                {
                    return RedirectToAction("Trips", "Trip", routeValues: new { customerId = user.Id });
                }

                trip = context.Trips.Where(t => t.UserId == user.Id && t.Id == tripId.Value).SingleOrDefault();
                if (trip == null)
                {
                    return RedirectToAction("Trips", "Trip", routeValues: new { customerId = user.Id });
                }
            }

            if (!tripId.HasValue)
            {
                return RedirectToAction("Customers", "Trip");
            }
    
            trip = context.Trips.Include(t => t.User)
                                    .Include(t => t.CarRentalReservations.Select(c => c.Vendor))
                                    .Include(t => t.FlightReservations.Select(f => f.Vendor))
                                    .Include(t => t.HotelReservations.Select(h => h.Vendor))
                                    .Where(t => t.Id == tripId).Single();
            ViewBag.TripId = tripId.Value;
            ViewBag.CustomerId = trip.UserId;
            TripDetailsViewModel model = new TripDetailsViewModel
            {
                Id = trip.Id,
                Name = trip.Name,
                Customer = trip.User.Name,
                CarRentals = trip.CarRentalReservations.Select(c => new CarRentalViewModel 
                                                                    { 
                                                                        Id = c.Id,
                                                                        CarType = c.CarType.ToString(),  
                                                                        StartDate = c.StartDate,
                                                                        EndDate = c.EndDate,
                                                                        Vendor = c.Vendor.Name,
                                                                        QuoteId = c.QuoteId,
                                                                        PricePerDay = c.PricePerDay,
                                                                        TotalPrice = c.TotalPrice,
                                                                        Status = c.Status.ToString()
                                                                    }).OrderBy(c => c.StartDate).ToList(),
                Flights = trip.FlightReservations.Select(f => new FlightViewModel
                                                                {
                                                                    Id = f.Id,
                                                                    SeatType = f.SeatType.ToString(),
                                                                    Count = f.Count,
                                                                    Date = f.Date,
                                                                    Departure = f.Departure,
                                                                    Destination = f.Destination,
                                                                    Vendor = f.Vendor.Name,
                                                                    QuoteId = f.QuoteId,
                                                                    PricePerSeat = f.PricePerSeat,
                                                                    TotalPrice = f.TotalPrice,
                                                                    Status = f.Status.ToString()
                                                                }).ToList(),
                Hotels = trip.HotelReservations.Select(h => new HotelViewModel
                                                            {
                                                                Id = h.Id,
                                                                RoomType = h.RoomType.ToString(),
                                                                Smoking = h.Smoking,
                                                                CheckIn = h.CheckIn,
                                                                CheckOut = h.CheckOut,
                                                                Vendor = h.Vendor.Name,
                                                                QuoteId = h.QuoteId,
                                                                PricePerNight = h.PricePerNight,
                                                                TotalPrice = h.TotalPrice,
                                                                Status = h.Status.ToString()
                                                            }).ToList()
            };
            return View(model);
        }

        #region Car Rental Actions
        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public PartialViewResult RequestCarRentalQuote(int tripId)
        {
            ViewBag.CustomerId = context.Trips.Where(t => t.Id == tripId).Single().UserId;
            ViewBag.TripId = tripId;
            ViewBag.CarTypes = Enum.GetValues(typeof(Domain.Entities.CarType)).Cast<Domain.Entities.CarType>().Select(e => e.ToString());
            return PartialView("_CarRentalQuotePartial", new CarRentalRequestViewModel { CarType = "Coupe", StartDate = DateTime.Now.AddDays(1), EndDate = DateTime.Now.AddDays(1) });
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public PartialViewResult RequestCarRentalQuote(CarRentalRequestViewModel model, int tripId)
        {
            Domain.Entities.Trip trip = context.Trips.Where(t => t.Id == tripId).Single();

            CarRental.Request request = new CarRental.Request
            {
                Type = (CarRental.CarType)Enum.Parse(typeof(CarRental.CarType), model.CarType),
                StartDate = model.StartDate,
                EndDate = model.EndDate
            };

            IEnumerable<Domain.Entities.Vendor> vendors = context.Vendors.Where(v => v.Type == Domain.Entities.VendorType.CarRental).AsEnumerable();
            foreach (Domain.Entities.Vendor v in vendors)
            {
                try
                {
                    using (CarRental.ServiceClient client = new CarRental.ServiceClient(v.Name, v.ServiceURL))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Password, passphrase);
                        CarRental.Quote quote = client.RequestQuote(request);
                        Domain.Entities.CarRentalReservation item = new Domain.Entities.CarRentalReservation
                        {
                            Trip = trip,
                            Vendor = v,
                            Status = Domain.Entities.ReservationStatus.Quoted,
                            QuoteId = quote.Id,
                            PricePerDay = quote.DailyPrice,
                            TotalPrice = quote.TotalPrice,
                            CarType = (Domain.Entities.CarType)Enum.Parse(typeof(Domain.Entities.CarType), model.CarType),
                            StartDate = model.StartDate,
                            EndDate = model.EndDate
                        };
                        context.CarRentalReservations.Add(item);
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
            }
            context.SaveChanges();

            List<CarRentalViewModel> carRentals = context.CarRentalReservations.Where(c => c.TripId == trip.Id).Select(c => new CarRentalViewModel
                                                                    {
                                                                        Id = c.Id,
                                                                        CarType = c.CarType.ToString(),
                                                                        StartDate = c.StartDate,
                                                                        EndDate = c.EndDate,
                                                                        Vendor = c.Vendor.Name,
                                                                        QuoteId = c.QuoteId,
                                                                        PricePerDay = c.PricePerDay,
                                                                        TotalPrice = c.TotalPrice,
                                                                        Status = c.Status.ToString()
                                                                    }).OrderBy(c => c.StartDate).ToList();

            return PartialView("_CarRentalsPartial", carRentals);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ReserveCarRental(int id)
        {
            Domain.Entities.CarRentalReservation reservation = context.CarRentalReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (CarRental.ServiceClient client = new CarRental.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    reservation.ReservationId = client.MakeReservation(reservation.QuoteId);
                    reservation.Status = Domain.Entities.ReservationStatus.Reserved;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation

            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult CancelCarRental(int id)
        {
            Domain.Entities.CarRentalReservation reservation = context.CarRentalReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (CarRental.ServiceClient client = new CarRental.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    client.CancelReservation(reservation.ReservationId.Value);
                    reservation.Status = Domain.Entities.ReservationStatus.Cancelled;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation
            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ConfirmCarRental(int id)
        {
            Domain.Entities.CarRentalReservation reservation = context.CarRentalReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            ViewBag.TripId = reservation.TripId;
            ViewBag.Id = id;
            ViewBag.CardTypes = Enum.GetValues(typeof(CarRental.CardType)).Cast<CarRental.CardType>().Select(e => e.ToString());
            TripConfirmationViewModel confirmation = new TripConfirmationViewModel
            {
                ReservationId = reservation.ReservationId.Value
            };
            return View(confirmation);
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public ActionResult ConfirmCarRental(TripConfirmationViewModel model, int id, int tripId)
        {
            if (ModelState.IsValid)
            {
                Domain.Entities.CarRentalReservation reservation = context.CarRentalReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
                string serviceName = reservation.Vendor.Name;
                string serviceUrl = reservation.Vendor.ServiceURL;
                try
                {
                    using (CarRental.ServiceClient client = new CarRental.ServiceClient(serviceName, serviceUrl))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                        CarRental.Confirmation confirmation = new CarRental.Confirmation
                        {
                            ReservationId = model.ReservationId,
                            Name = model.Name,
                            AddressLine1 = model.Address1,
                            AddressLine2 = model.Address2,
                            City = model.City,
                            State = model.State,
                            ZipCode = model.ZipCode,
                            CardType = (CarRental.CardType)Enum.Parse(typeof(CarRental.CardType), model.CardType),
                            CardNumber = model.CardNumber,
                            CardExpirationMonth = model.ExpirationMonth,
                            CardExpirationYear = model.ExpirationYear,
                        };
                        client.ConfirmReservation(confirmation);
                        reservation.Status = Domain.Entities.ReservationStatus.Confirmed;
                        context.SaveChanges();
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
                return RedirectToAction("Edit", "Trip", new { tripId = tripId });
            }
            ViewBag.TripId = tripId;
            ViewBag.Id = id;
            return View(model);
        }
        #endregion

        #region Flight Actions
        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public PartialViewResult RequestFlightQuote(int tripId)
        {
            ViewBag.CustomerId = context.Trips.Where(t => t.Id == tripId).Single().UserId;
            ViewBag.TripId = tripId;
            ViewBag.SeatTypes = Enum.GetValues(typeof(Domain.Entities.SeatType)).Cast<Domain.Entities.SeatType>().Select(e => e.ToString());
            return PartialView("_FlightQuotePartial", new FlightRequestViewModel { SeatType = "EconomyClass", Date = DateTime.Now.AddDays(1), Count = 1 });
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public PartialViewResult RequestFlightQuote(FlightRequestViewModel model, int tripId)
        {
            Domain.Entities.Trip trip = context.Trips.Where(t => t.Id == tripId).Single();

            Flight.Request request = new Flight.Request
            {
                Type = (Flight.SeatType)Enum.Parse(typeof(Flight.SeatType), model.SeatType),
                Count = model.Count,
                Date = model.Date,
                Departure = model.Departure,
                Destination = model.Destination
            };

            IEnumerable<Domain.Entities.Vendor> vendors = context.Vendors.Where(v => v.Type == Domain.Entities.VendorType.Flight).AsEnumerable();
            foreach (Domain.Entities.Vendor v in vendors)
            {
                try
                {
                    using (Flight.ServiceClient client = new Flight.ServiceClient(v.Name, v.ServiceURL))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Password, passphrase);
                        Flight.Quote quote = client.RequestQuote(request);
                        Domain.Entities.FlightReservation item = new Domain.Entities.FlightReservation
                        {
                            Trip = trip,
                            Vendor = v,
                            Status = Domain.Entities.ReservationStatus.Quoted,
                            QuoteId = quote.Id,
                            PricePerSeat = quote.PricePerSeat,
                            TotalPrice = quote.TotalPrice,
                            SeatType = (Domain.Entities.SeatType)Enum.Parse(typeof(Domain.Entities.SeatType), model.SeatType),
                            Date = model.Date,
                            Departure = model.Departure,
                            Destination = model.Destination
                        };
                        context.FlightReservations.Add(item);
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
            }
            context.SaveChanges();

            List<FlightViewModel> flights = context.FlightReservations.Where(c => c.TripId == trip.Id).Select(c => new FlightViewModel
            {
                Id = c.Id,
                SeatType = c.SeatType.ToString(),
                Date = c.Date,
                Departure = c.Departure,
                Destination = c.Destination,
                Count = c.Count,
                Vendor = c.Vendor.Name,
                QuoteId = c.QuoteId,
                PricePerSeat = c.PricePerSeat,
                TotalPrice = c.TotalPrice,
                Status = c.Status.ToString()
            }).OrderBy(c => c.Date).ToList();

            return PartialView("_FlightsPartial", flights);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ReserveFlight(int id)
        {
            Domain.Entities.FlightReservation reservation = context.FlightReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (Flight.ServiceClient client = new Flight.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    reservation.ReservationId = client.MakeReservation(reservation.QuoteId);
                    reservation.Status = Domain.Entities.ReservationStatus.Reserved;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation

            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult CancelFlight(int id)
        {
            Domain.Entities.FlightReservation reservation = context.FlightReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (Flight.ServiceClient client = new Flight.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    client.CancelReservation(reservation.ReservationId.Value);
                    reservation.Status = Domain.Entities.ReservationStatus.Cancelled;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation
            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ConfirmFlight(int id)
        {
            Domain.Entities.FlightReservation reservation = context.FlightReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            ViewBag.TripId = reservation.TripId;
            ViewBag.Id = id;
            ViewBag.CardTypes = Enum.GetValues(typeof(Flight.CardType)).Cast<Flight.CardType>().Select(e => e.ToString());
            TripConfirmationViewModel confirmation = new TripConfirmationViewModel
            {
                ReservationId = reservation.ReservationId.Value
            };
            return View(confirmation);
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public ActionResult ConfirmFlight(TripConfirmationViewModel model, int id, int tripId)
        {
            if (ModelState.IsValid)
            {
                Domain.Entities.FlightReservation reservation = context.FlightReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
                string serviceName = reservation.Vendor.Name;
                string serviceUrl = reservation.Vendor.ServiceURL;
                try
                {
                    using (Flight.ServiceClient client = new Flight.ServiceClient(serviceName, serviceUrl))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                        Flight.Confirmation confirmation = new Flight.Confirmation
                        {
                            ReservationId = model.ReservationId,
                            Name = model.Name,
                            AddressLine1 = model.Address1,
                            AddressLine2 = model.Address2,
                            City = model.City,
                            State = model.State,
                            ZipCode = model.ZipCode,
                            CardType = (Flight.CardType)Enum.Parse(typeof(Flight.CardType), model.CardType),
                            CardNumber = model.CardNumber,
                            CardExpirationMonth = model.ExpirationMonth,
                            CardExpirationYear = model.ExpirationYear,
                        };
                        client.ConfirmReservation(confirmation);
                        reservation.Status = Domain.Entities.ReservationStatus.Confirmed;
                        context.SaveChanges();
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
                return RedirectToAction("Edit", "Trip", new { tripId = tripId });
            }
            ViewBag.TripId = tripId;
            ViewBag.Id = id;
            return View(model);
        }
        #endregion

        #region Hotel Actions
        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public PartialViewResult RequestHotelQuote(int tripId)
        {
            ViewBag.CustomerId = context.Trips.Where(t => t.Id == tripId).Single().UserId;
            ViewBag.TripId = tripId;
            ViewBag.RoomTypes = Enum.GetValues(typeof(Domain.Entities.RoomType)).Cast<Domain.Entities.RoomType>().Select(e => e.ToString());
            return PartialView("_HotelQuotePartial", new HotelRequestViewModel { RoomType = "Doubles", CheckIn = DateTime.Now.AddDays(1), CheckOut = DateTime.Now.AddDays(2) });
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public PartialViewResult RequestHotelQuote(HotelRequestViewModel model, int tripId)
        {
            Domain.Entities.Trip trip = context.Trips.Where(t => t.Id == tripId).Single();

            Hotel.Request request = new Hotel.Request
            {
                Type = (Hotel.RoomType)Enum.Parse(typeof(Hotel.RoomType), model.RoomType),
                CheckIn = model.CheckIn,
                CheckOut = model.CheckOut,
                Smoking = model.Smoking
            };

            IEnumerable<Domain.Entities.Vendor> vendors = context.Vendors.Where(v => v.Type == Domain.Entities.VendorType.Hotel).AsEnumerable();
            foreach (Domain.Entities.Vendor v in vendors)
            {
                try
                {
                    string serviceName = v.Name.Replace(" ", string.Empty);
                    using (Hotel.ServiceClient client = new Hotel.ServiceClient(serviceName, v.ServiceURL))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(v.Password, passphrase);
                        Hotel.Quote quote = client.RequestQuote(request);
                        Domain.Entities.HotelReservation item = new Domain.Entities.HotelReservation
                        {
                            Trip = trip,
                            Vendor = v,
                            Status = Domain.Entities.ReservationStatus.Quoted,
                            QuoteId = quote.Id,
                            PricePerNight = quote.PricePerNight,
                            TotalPrice = quote.TotalPrice,
                            RoomType = (Domain.Entities.RoomType)Enum.Parse(typeof(Domain.Entities.RoomType), model.RoomType),
                            Smoking = model.Smoking,
                            CheckIn = model.CheckIn,
                            CheckOut = model.CheckOut
                        };
                        context.HotelReservations.Add(item);
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
            }
            context.SaveChanges();

            List<HotelViewModel> hotels = context.HotelReservations.Where(c => c.TripId == trip.Id).Select(c => new HotelViewModel
            {
                Id = c.Id,
                RoomType = c.RoomType.ToString(),
                CheckIn = c.CheckIn,
                CheckOut = c.CheckOut,
                Smoking = c.Smoking,
                Vendor = c.Vendor.Name,
                QuoteId = c.QuoteId,
                PricePerNight = c.PricePerNight,
                TotalPrice = c.TotalPrice,
                Status = c.Status.ToString()
            }).OrderBy(c => c.CheckIn).ToList();

            return PartialView("_HotelsPartial", hotels);
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ReserveHotel(int id)
        {
            Domain.Entities.HotelReservation reservation = context.HotelReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (Hotel.ServiceClient client = new Hotel.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    reservation.ReservationId = client.MakeReservation(reservation.QuoteId);
                    reservation.Status = Domain.Entities.ReservationStatus.Reserved;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation

            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult CancelHotel(int id)
        {
            Domain.Entities.HotelReservation reservation = context.HotelReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            string serviceName = reservation.Vendor.Name;
            string serviceUrl = reservation.Vendor.ServiceURL;
            try
            {
                using (Hotel.ServiceClient client = new Hotel.ServiceClient(serviceName, serviceUrl))
                {
                    string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                    client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                    client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                    client.CancelReservation(reservation.ReservationId.Value);
                    reservation.Status = Domain.Entities.ReservationStatus.Cancelled;
                    context.SaveChanges();
                }
            }
            catch { } // we aren't worried about these errors for this simulation
            return RedirectToAction("Edit", "Trip", new { tripId = reservation.TripId });
        }

        [RequireHttps]
        [HttpGet]
        [Authorize(Roles = "Agents, Customers")]
        public ActionResult ConfirmHotel(int id)
        {
            Domain.Entities.HotelReservation reservation = context.HotelReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
            ViewBag.TripId = reservation.TripId;
            ViewBag.Id = id;
            ViewBag.CardTypes = Enum.GetValues(typeof(Hotel.CardType)).Cast<Hotel.CardType>().Select(e => e.ToString());
            TripConfirmationViewModel confirmation = new TripConfirmationViewModel
            {
                ReservationId = reservation.ReservationId.Value
            };
            return View(confirmation);
        }

        [RequireHttps]
        [HttpPost]
        [Authorize(Roles = "Agents, Customers")]
        [ValidateAntiForgeryToken]
        public ActionResult ConfirmHotel(TripConfirmationViewModel model, int id, int tripId)
        {
            if (ModelState.IsValid)
            {
                Domain.Entities.HotelReservation reservation = context.HotelReservations.Where(c => c.Id == id).Include(c => c.Trip.User).Include(c => c.Vendor).Single();
                string serviceName = reservation.Vendor.Name;
                string serviceUrl = reservation.Vendor.ServiceURL;
                try
                {
                    using (Hotel.ServiceClient client = new Hotel.ServiceClient(serviceName, serviceUrl))
                    {
                        string passphrase = System.Configuration.ConfigurationManager.AppSettings["passphrase"];
                        client.ClientCredentials.UserName.UserName = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Username, passphrase);
                        client.ClientCredentials.UserName.Password = CS795.TravelAgency.Encryption.AESEncryption.Decrypt(reservation.Vendor.Password, passphrase);
                        Hotel.Confirmation confirmation = new Hotel.Confirmation
                        {
                            ReservationId = model.ReservationId,
                            Name = model.Name,
                            AddressLine1 = model.Address1,
                            AddressLine2 = model.Address2,
                            City = model.City,
                            State = model.State,
                            ZipCode = model.ZipCode,
                            CardType = (Hotel.CardType)Enum.Parse(typeof(Hotel.CardType), model.CardType),
                            CardNumber = model.CardNumber,
                            CardExpirationMonth = model.ExpirationMonth,
                            CardExpirationYear = model.ExpirationYear,
                        };
                        client.ConfirmReservation(confirmation);
                        reservation.Status = Domain.Entities.ReservationStatus.Confirmed;
                        context.SaveChanges();
                    }
                }
                catch { } // we aren't worried about these errors for this simulation
                return RedirectToAction("Edit", "Trip", new { tripId = tripId });
            }
            ViewBag.TripId = tripId;
            ViewBag.Id = id;
            return View(model);
        }
        #endregion
    }
}